﻿using System;
using System.Collections.Generic;
using System.Linq;
using MIAP.DataAccess.Interfaces;
using MIAP.Entidades;
using MIAP.Entidades.Enums;

namespace MIAP.Negocio
{
    public class CargaArchivosNegocio
    {
        #region Campos

        /// <summary>
        /// Instancia para el acceso a datos de Archivos.
        /// </summary>
        private readonly IArchivosDao daoArchivos;

        /// <summary>
        /// Instancia para el acceso a datos de Archivos.
        /// </summary>
        private readonly ICargasArchivosDao daoCargaArchivos;

        /// <summary>
        /// instancia para el acceso a las consultas de las cargas
        /// </summary>
        private readonly IConsultaCargasProyectoDao daoConsultaCargas;

        #endregion

        #region Constructor

        /// <summary>
        /// Inicializa una instancia de <see cref="CargaArchivosNegocio"/>
        /// </summary>
        public CargaArchivosNegocio()
        {
            this.daoArchivos = DataAccessFactory.Instance.CreateArchivosDao();
            this.daoCargaArchivos = DataAccessFactory.Instance.CreateCargasArchivosDao();
            this.daoConsultaCargas = DataAccessFactory.Instance.CreateConsultaCargasProyectoDao();
        }

        #endregion

        /// <summary>
        /// Obtiene todos los Archivos activos de un proyecto en especifico de un usuario en los que puede cargar información
        /// </summary>
        /// <param name="idProyecto">Es el id del proyecto del cual queremos obtener los archivos relacionados</param>
        /// <param name="idUsuario">Id del usuario a filtrar</param>
        /// <returns>Lista con todos los Archivos.</returns>
        public List<ArchivoInfo> GetArchivosCarga(int idProyecto, int idUsuario)
        {
            return this.daoArchivos.GetArchivosCarga(idProyecto, idUsuario).ToList();
        }

        /// <summary>
        /// Obtiene la información de un determinado Archivo.
        /// </summary>
        /// <param name="idArchivo">Es el id del Archivo del que se desea obtener la informacion.</param>
        /// <returns>Información general del Archivo.</returns>
        public ArchivoInfo GetArchivoById(int idArchivo)
        {
            return this.daoArchivos.GetArchivoById(idArchivo);
        }

        /// <summary>
        /// Obtiene la lista de objetos autorizados
        /// </summary>
        /// <param name="idUser"></param>
        /// <returns></returns>
        public List<CatalogoInfo> GetArchivosAutorizados(int idUser)
        {
            var lista = this.daoCargaArchivos.GetArchivosAutorizados(idUser);
            var listRetorno = (from archivo in lista
                               select new CatalogoInfo
                               {
                                   IdItem = archivo.IdArchivo.Value,
                                   Descripcion = archivo.NombreArchivo +
                                   (string.IsNullOrEmpty(archivo.Version) ? string.Empty : (" -- " + archivo.Version))
                               }).ToList();
            return listRetorno;
        }

        /// <summary>
        /// Obtenemos el archivo que identifica la carga del archivo y version
        /// </summary>
        /// <param name="idArchivo"></param>
        /// <param name="version"></param>
        /// <returns></returns>
        public CargaArchivoInfo GetArchivoCarga(int idArchivo, string version)
        {
            var archivos = this.daoCargaArchivos.GetInformacionArchivoCarga(idArchivo, version);

            return archivos.Count >= 1 ? archivos.OrderByDescending(a => a.FechaProceso).First() : null;
        }

        /// <summary>
        /// Obtiene la version siguiente del archivo dependiendo año y mes
        /// </summary>
        /// <param name="idArchivo">id del archivo a obtenr version</param>
        /// <param name="año">año de la version</param>
        /// <param name="mes">mes de la version</param>
        /// <returns></returns>
        public string GetVersionCargar(int idArchivo, int año, int? mes)
        {
            var versionInicial = año + "-1";
            var archivos = this.daoCargaArchivos.GetInformacionArchivoCarga(idArchivo, null);

            var versiones = (from loArchivo in archivos
                             where loArchivo.Version.Contains(año.ToString())
                             select loArchivo.Version).ToList();
            if (versiones.Count == 0)
            {
                return versionInicial;
            }
            //versiones = mes.HasValue ? (from loArchivo in archivos
            //                            where loArchivo.Version.Contains("_" + mes)
            //                            select loArchivo.Version).ToList() :
            //    (from loArchivo in archivos
            //     where !loArchivo.Version.Contains("_")
            //     select loArchivo.Version).ToList();

            //if (versiones.Count == 0)
            //{
            //    return versionInicial;
            //}

            var verSig = (from version in versiones select Convert.ToInt32(version.Split('-')[1])).Max() + 1;

            //return año + (mes.HasValue ? ("_" + mes) : string.Empty) + ("-" + verSig);
            return año + ("-" + verSig);
        }

        /// <summary>
        /// Registra una nueva carga de archivo en el sistema y regresa el ID de la bitacora general
        /// </summary>
        /// <param name="archivo">informacion del archivo que registraremos la carga</param>
        /// <param name="user">usuario que esta realizando la carga</param>
        public int CargaArchivo(CargaArchivoInfo archivo, UsuarioInfo user)
        {
            return this.daoCargaArchivos.CargaArchivo(archivo, user);
        }

        /// <summary>
        /// Registra una re-Carga de archivo en el sistema
        /// </summary>
        /// <param name="archivo">informacion del archivo que registraremos la carga</param>
        /// <param name="user">usuario que esta realizando la carga</param>
        public int RecargaArchivo(CargaArchivoInfo archivo, UsuarioInfo user)
        {
            return this.daoCargaArchivos.RecargaArchivo(archivo, user);
        }

        /// <summary>
        /// Valida si ya existen archivos cargados en el mes y año correspondiente
        /// </summary>
        /// <param name="idProyecto">id del proyecto en el que se encuentra el archivo</param>
        /// <param name="idArchivo">id del archivo a verificar</param>
        /// <param name="año">año a verificar</param>
        /// <param name="mes">mes a verificar</param>
        /// <returns>true si ya existe mas de un archivo cargado, false en caso contrario</returns>
        public bool ValidaArchivoCargado(int idProyecto, int idArchivo, int año, int mes)
        {
            var filtroSolicitud = new ArchivoAsociadoProyectoInfo()
                {
                    IdProyecto = idProyecto,
                    Año = año,
                    Mes = mes
                };

            var listCargasRealizadas = this.daoConsultaCargas.GetCargasRealizadasByPeriodoTodosEstatus(filtroSolicitud).ToList();

            var listCargasRealizadasByArchivo = ComunesNegocio.GetArchivoWithLastProcess(listCargasRealizadas);
                                 
            return listCargasRealizadasByArchivo.Any(elemento => elemento.IdArchivo == idArchivo && elemento.IdEstatusProceso != (int)EstatusProceso.Finalizado_Errores);
        }
    }
}
